package com.cardeira.sendsms.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.xml.sax.SAXException;

import com.cardeira.sendsms.client.SMSService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.cardeira.sendsms.client.data.SmsEntry;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class SMSServiceImpl extends RemoteServiceServlet implements
		SMSService {
	private static final Logger log = Logger.getLogger(SMSServiceImpl.class.getName());
	

	private static final String smsUrlFormat = "http://www.panelsms.com/gateway/mtsms1.php?notify=AEX&remitente=%5$s&user=Jcardeira&password="+getPassword()+"&moviles=%%2B%1$s&contenido=%2$s&idenvio=%3$d&ruta=%4$d";


	private static final String smsUrlNowsms = null;


	
	//@Override
	public int[] getStatus(String[] reqs) {
		int[] res=new int[reqs.length];
		String  url;

		PersistenceManager pm = PMF.get().getPersistenceManager();
		for(int i=0; i<reqs.length; i++)
		{
			com.cardeira.sendsms.server.SmsEntry s = (com.cardeira.sendsms.server.SmsEntry)pm.getObjectById(com.cardeira.sendsms.server.SmsEntry.class, reqs[i]);
			if (s.getMnc().equals("26806"))
				res[i]=s.getDeliveryStatus();
			else
			{
			url = "http://www.panelsms.com/gateway/consultar_estado_envio_id.php?pais=351&user=Jcardeira&password="+getPassword()+"&idenvio="+reqs[i];
			log.log(Level.INFO, "invoking: "+url);
			res[i]=translateDeliveryStatus(url);
			}
		}
		return res;			
	}

	
	private static String getPassword() {
		
		return "Vitaldente";
	}


	/*
	 * <envios>
	 * 	<encontrados>1</encontrados>
	 * 	<datos>
	 * 	<detalle>
	 * 		<id_envio>1234</id_envio>
	 * 		<movil>912381488</movil>
	 * 		<fecha_entrada>2011-05-21</fecha_entrada>
	 * 		<hora_entrada>01:24:23</hora_entrada>
	 * 		<texto_envio>teste1234</texto_envio>
	 * 		<fecha_entregaoperadora></fecha_entregaoperadora>
	 * 		<hora_entregaoperadora></hora_entregaoperadora>
	 * 		<fecha_notificacion>2011-05-21</fecha_notificacion>
	 * 		<hora_notificacion>01:23:09</hora_notificacion>
	 * 		<estado>N.ENVIADO</estado>
	 * 	</detalle>
	 * 	</datos>
	 * </envios>
	 * 
	 * 
	 */
	private int translateDeliveryStatus(String url) {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		//Using factory get an instance of document builder
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
			org.w3c.dom.Document dom = db.parse(url);
			XPathFactory factory = XPathFactory.newInstance();
			XPath xpath = factory.newXPath();
			XPathExpression expr = xpath.compile("/envios/datos/detalle/estado");
			String result = expr.evaluate(dom);
			log.log(Level.INFO, "result = "+result);
			if (result.equals("")) return 3;
			if (result.equals("N.ENVIADO")) return 4;
			if (result.toUpperCase().equals("N. ALMACENADO")) return 3;
			if (result.toUpperCase().equals("ERROR")) return 5;
			return 3;	
		} catch (ParserConfigurationException e) {
			
			e.printStackTrace();
		} catch (SAXException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			
			e.printStackTrace();
		}
		return 5;
	}

	@Override
	public SmsEntry sendSMS(SmsEntry e) 		{
		int dayOfWeek = Calendar.getInstance(TimeZone.getTimeZone("GMT")).get(Calendar.DAY_OF_WEEK);
		String quando;
		if (dayOfWeek == Calendar.SATURDAY)
			quando = "segunda-feira";
		else
			quando = e.getDay();
		e.setText(e.getClinica()+". Lembramos que tem uma consulta "+quando+" as "+e.getAppTime()+". Caso nao possa comparecer por favor contacte-nos pelo "+e.getSenderPhone()+".");	
		if (e.getPatient()!=null)
		{
			String text = e.getClinica()+". "+e.getPatient()+", lembramos que tem uma consulta "+quando+" as "+e.getAppTime()+". Caso nao possa comparecer por favor contacte-nos pelo "+e.getSenderPhone()+".";	
			e.setText(text);
		}
		String mnc = getMNC(e.getPhoneNumber());
		invokeSendSms(e.getPhoneNumber(), e.getText(), e.getSenderID(), mnc, e.getKey());
		e.setMNC(mnc);
		return e;		
	}	

	private String invokeSendSms(String phoneNumber, String text, String senderID, String mnc, String id) {
		try {
			text = URLEncoder.encode(text, "windows-1252");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		String url;
		if (mnc.equals("26806"))
			url=String.format(smsUrlNowsms, phoneNumber, text, id);
		else
			url=String.format(smsUrlFormat, phoneNumber, text, id, 4, senderID);
		
		log.log(Level.INFO, "invoking; "+url);
		String res = invokeUrl(url);
		log.log(Level.INFO, "received: "+res);
		return id;
	}

	private String getMNC(String phoneNumber) {
		
		return invokeUrl("http://smsgateway.inosat.com/hlrlookup.aspx?msisdn="+phoneNumber);
	}


	private String invokeUrl(String urlAddress) {
		try {
			URL url;
			
			BufferedReader in;
			String res="";
				url = new URL(urlAddress);
				HttpURLConnection connection = (HttpURLConnection) url.openConnection();
				 connection.setRequestProperty("Cache-Control", "no-cache,max-age=0");
				 connection.setRequestProperty("Pragma", "no-cache");
				
	            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
	            	
	            	in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
	    			res = in.readLine();
	    			in.close();
	            } else {
	                log.log(Level.WARNING, "couldn't fetch url. "+connection.getResponseCode());
	            }

			
			return res;
		} catch (MalformedURLException e1) {
			
			e1.printStackTrace();
		}
		 catch (IOException e) {
				e.printStackTrace();
			}		
		return null;
	}

	@Override
	public SmsEntry[] getImported(String guid) {
		log.entering("SMSServiceImpl", "getImported");
		
	     PersistenceManager pm = PMF.get().getPersistenceManager();

		Query query = pm.newQuery(com.cardeira.sendsms.server.SmsEntry.class);
	    query.setFilter("guid == '"+guid+"'");

	    List<SmsEntry> l = new ArrayList<SmsEntry>();

	    try {
	    	@SuppressWarnings("unchecked")
			List<com.cardeira.sendsms.server.SmsEntry> results=  (List<com.cardeira.sendsms.server.SmsEntry>) query.execute();
	    	log.info("got "+results.size()+ " results");
	    	Iterator<com.cardeira.sendsms.server.SmsEntry> it = results.iterator();
	    	while (it.hasNext())
	    	{
	    		log.info("adding one smsentry...");
	    		com.cardeira.sendsms.server.SmsEntry se =it.next();
	    		SmsEntry ce = new SmsEntry();
	    		ce.setText(se.getText());
	    		ce.setPhoneNumber(se.getPhoneNumber());
	    		ce.setClinica(se.getClinica());
	    		ce.setDay(se.getDay());
	    		ce.setAppTime(se.getAppTime());
	    		ce.setPatient(se.getPatient());
	    		ce.setSenderPhone(se.getSenderPhone());
	    		ce.setSenderID(se.getSenderID());
	    		ce.setKey(se.GetKey());
	    		l.add(ce);
	    		
	    	}
	    	//pm.deletePersistentAll(results);
	    	
	        if (l.size()>0) {
	        	return l.toArray(new SmsEntry[l.size()]);
	            
	        } else {
	            return null;
	        }	    
	    }
	    catch(Throwable e)
	    {
	    	log.log(Level.SEVERE, e.getMessage(), e);
	    	return null;
	    }
	    finally {
	        query.closeAll();
	    }
	}
}
